package com.rankeiot.core.inner;

import com.rankeiot.core.exception.BusinessException;
import com.rankeiot.core.inner.argumet.QueryParams;
import com.rankeiot.core.util.JSONUtil;
import com.rankeiot.core.util.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;


import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class QueryParamsMethodArgumentResolver implements HandlerMethodArgumentResolver {
    private final String SORT="sort";
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return QueryParams.class==parameter.getParameterType();
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        QueryParams query = new QueryParams();

        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

        if( inputMessage.getMethod()== HttpMethod.GET||inputMessage.getMethod()== HttpMethod.DELETE){

        }else if(inputMessage.getHeaders().getContentType().equalsTypeAndSubtype(MediaType.APPLICATION_JSON)){
            String body= StringUtil.read(inputMessage.getBody());
            if(StringUtil.isEmpty(body)){
                return query;
            }
            query.setParams(new HashMap<>());
            query.getParams().putAll(filterNames(JSONUtil.parseObject(body)));
            return query;
        }

        Map<String, String[]> parameterMap = webRequest.getParameterMap();
        HashMap<String,Object> params= new LinkedHashMap<>(parameterMap.size());
        parameterMap.forEach((key, values) -> {
            if (values.length > 0) {
                params.put(key, values[0]);
            }
        });
        if(params.containsKey(SORT)){
            String sort=query.getStr(SORT);
            if(StringUtil.isNotEmpty(sort)){
                validateSort(sort);
            }
        }
        filterNames(params);
        query.setParams(params);

        return query;
    }
    public static Map filterNames(Map params){
        if(params!=null){
            params.remove("include");
            params.remove("scope");
        }
        return params;
    }
    public static void validateSort(String sortStr){
        if(StringUtil.isEmpty(sortStr)){
            return;
        }
        String[] sortParts=sortStr.split(",");
        for(String part:sortParts){
            String[] ps=part.split("\\s+");
            if(ps.length!=2){
                throw new BusinessException("排序错误");
            }
            validateSort(ps[0],ps[1]);
        }
    }
    private enum SortType{
        DESC,ASC
    }
    private static Pattern fieldPattern=Pattern.compile("^\\w+$");
    private static void validateSort(String field,String type){
        if(SortType.valueOf(type.toUpperCase())==null){
            throw new BusinessException("排序类型错误");
        }
        if(!fieldPattern.matcher(field).matches()){
            throw new BusinessException("排序字段错误");
        }
    }
}
